﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using NesGfx;
namespace cnetmegamanprj
{
    public partial class WorldEdit : Form
    {
        LevelData worldEdit;
        readonly int tileWidth = 8, tileHeight = 8, worldMultiply = 2;
        //readonly int tsaC = 8, tsaR = 8;
        Bitmap b, b2;
        Render render, renderTsa;

        int screenNumber = 0;
        bool isShiftDown = false; //its so lame i need to do this
        MegaMan mm;

        //public WorldEdit(LevelData w)
        public WorldEdit(MegaMan mm_)
        {
            InitializeComponent();
            mm = mm_;
            worldEdit = mm.getLevelData(0);
            var w = worldEdit;
            var d = w.tsaEdit;
            b = new Bitmap(tileWidth * w.tsaCol * (int)d.tsa.c * worldMultiply,
                            tileHeight * w.tsaRow * (int)d.tsa.r * worldMultiply);
            b2 = new Bitmap(tileWidth * d.displayC * (int)d.tsa.c * worldMultiply, tileHeight * d.displayR * (int)d.tsa.r * worldMultiply);
            render = new Render(d.chrdata, b, worldMultiply);
            renderTsa = new Render(d.chrdata, b2, worldMultiply);
        }

        void PicKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            Level_KeyDown(sender, new KeyEventArgs(e.KeyData));
        }

        private void WorldEdit_Load(object sender, EventArgs e)
        {
            this.KeyPreview = true;
            //this.KeyPreview = true;
            pictureBox1.Image = b;
            pictureBox1.Width = b.Width;
            pictureBox1.Height = b.Height;
            pictureBox1.MouseMove += pictureBox1_MouseMove;
            pictureBox1.MouseDown += pictureBox1_MouseDown;

            pictureBox1.KeyDown += Level_KeyDown;
            pictureBox1.MouseWheel += pictureBox2.ScrollEvent;
            pictureBox1.MouseMove += pictureBox2.ScrollEvent;

            pictureBox2.pic.KeyDown += Level_KeyDown;
            pictureBox2.pic.MouseWheel += pictureBox2.ScrollEvent;
            pictureBox2.pic.MouseMove += pictureBox2.ScrollEvent;

            pictureBox2.pic.MouseDown += pictureBox2_MouseDown;
            pictureBox2.pic.Paint+= pictureBox2_Paint;
            pictureBox2.pic.DoubleClick += pictureBox2_DoubleClick;

            pictureBox2.Set(256, 512, b2, 32);
            pictureBox2.Paint += pictureBox2_Paint;
            //pictureBox2.Set(b2.Width/2, b2.Height, b2);
            //pictureBox2.Image = b2;
            //pictureBox2.Width = b2.Width;
            //pictureBox2.Height = b2.Height;
            pictureBox2.Left = pictureBox1.Right + 10;
            pictureBox2.Top = pictureBox1.Top;

            this.Height = pictureBox1.Bottom + 42;
            this.Width = pictureBox2.Right + 20;

            panel1.Left = pictureBox2.Right + 10;

            comboBox1.Items.AddRange(Form1.mm.LevelNames);
            comboBox1.SelectedIndex = 0;

            /*
            //comboBox1.Top = pictureBox1.Bottom + 16;
            //comboBox1.Left = pictureBox1.Left;
            comboBox1.Top = pictureBox1.Top;
            comboBox1.Left = pictureBox2.Right + 10;


            label1.Left = comboBox1.Left;
            label2.Left = comboBox1.Left;
            //*/
            SetTsaText(0);

            draw(screenNumber);
            drawTsa();
            this.WindowState = FormWindowState.Maximized;
            pictureBox1.Focus();
        }

        void SetTsaText(int index)//, int c, int r)
        {
            var c = index % 16;
            var r = index / 16;
            label1.Text = string.Format("TSA Index: {0} ({1},{2})", index, c, r);
        }

        int getHighBits(int room, int v)
        {
            return worldEdit.paletteIndex == null ? worldEdit.tsaEdit.highBits[v] : worldEdit.paletteIndex[room, v];
        }
        void drawTsa()
        {
            var render = renderTsa;
            var d = worldEdit.tsaEdit;
            int w = (int)d.tsa.c * tileWidth * worldMultiply;
            int h = (int)d.tsa.r * tileHeight * worldMultiply;

            render.lockIt();

            for (int y = 0; y < d.displayR; y++)
            {
                for (int x = 0; x < d.displayC; x++)
                {
                    var palOff = getHighBits(screenNumber, y * d.displayC + x) * 4;
                    render.pal.setPalette(d.pal, palOff);
                    render.Draw(d.tsa[(uint)(y * d.displayC + x)], x * w, y * h, d.tileMap);
                }
            }//*/
            render.unlockIt();
            pictureBox1.Invalidate();
        }
        void draw(int screenNumber)
        {
            //this.Text = "Drawing screen #" + screenNumber.ToString();
            label5.Text = screenNumber.ToString();
            var d = worldEdit.tsaEdit;
            int w = (int)d.tsa.c * tileWidth * worldMultiply;
            int h = (int)d.tsa.r * tileHeight * worldMultiply;

            render.lockIt();
            //render.Draw(d.tsa[0], 0 * w, 0 * h);

            var totalCol = worldEdit.tsaCol;
            for (int y = 0; y < worldEdit.tsaRow; y++)
            {
                for (int x = 0; x < totalCol; x++)
                {
                    var tsaIndex = worldEdit.worldMap[screenNumber, y * totalCol + x];
                    var palOff = getHighBits(screenNumber, (y * worldEdit.tsaRow) + x) * 4;
                    render.pal.setPalette(d.pal, palOff);
                    render.Draw(d.tsa[tsaIndex], x * w, y * h, d.tileMap);
                }
            }
            render.unlockIt();
            pictureBox1.Invalidate();
        }

        private void WorldEdit_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                this.Close();
                return;
            }
        }
        private void Level_KeyDown(object sender, KeyEventArgs e)
        {
            isShiftDown = e.Shift;
            int orgNum = screenNumber;
            if (e.KeyCode == Keys.Escape) this.Close();

            if (isShiftDown || e.Modifiers == Keys.Control)
            {
                if ((e.KeyCode == Keys.Left) || (e.KeyCode == Keys.A))
                    screenNumber = 0;
                else if ((e.KeyCode == Keys.Right) || (e.KeyCode == Keys.D))
                {
                    screenNumber++;
                }
            }
            else
            {
                if ((e.KeyCode == Keys.Left) || (e.KeyCode == Keys.A))
                {
                    if (screenNumber > 0)
                        screenNumber--;
                }
                else if ((e.KeyCode == Keys.Right) || (e.KeyCode == Keys.D))
                {
                    screenNumber++;
                }
                else if ((e.KeyCode >= Keys.D1) && (e.KeyCode <= Keys.D4))
                {
                    var x2 = lastX;
                    var y2 = lastY;
                    int x = (x2 == 0 ? 0 : x2 / (tileWidth * (int)worldEdit.tsaEdit.tsa.c * worldMultiply));
                    int y = (y2 == 0 ? 0 : y2 / (tileHeight * (int)worldEdit.tsaEdit.tsa.r * worldMultiply));
                    worldEdit.paletteIndex[screenNumber, (y * worldEdit.tsaRow) + x] = (byte)(e.KeyCode - Keys.D1);
                    label7.Text = worldEdit.paletteIndex[screenNumber, (y * worldEdit.tsaRow) + x].ToString();
                    draw(screenNumber);
                }
            }
            
            if(e.KeyCode == Keys.Home)
            {
                screenNumber=0;
            }

            if (orgNum != screenNumber)
            {
                tsaMove = getTsaNo(lastX, lastY, screenNumber);
                pictureBox2.pic.Invalidate();
                draw(screenNumber);
            }
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {

        }

        private void pictureBox2_Click(object sender, EventArgs e)
        {

        }

        private void pictureBox2_Paint(object sender, PaintEventArgs e)
        {
            int hc = tsaMove % worldEdit.tsaEdit.displayC;
            int hr = tsaMove / worldEdit.tsaEdit.displayC;
            var pen = new Pen(Color.Yellow, 1);
            var d = worldEdit.tsaEdit.tsa;
            var r = new Rectangle(
                hc * tileWidth *(int)d.c * worldMultiply-1,
                hr * tileHeight * (int)d.r * worldMultiply - 1,
                tileWidth * (int)d.c * worldMultiply + 1,
                tileHeight * (int)d.r * worldMultiply + 1);
            e.Graphics.DrawRectangle(pen, r);

            hc = tsaSelect % worldEdit.tsaEdit.displayC;
            hr = tsaSelect / worldEdit.tsaEdit.displayC;
            pen = new Pen(tsaMove == tsaSelect ? Color.GreenYellow : Color.LightGreen, 1);
            r = new Rectangle(
                hc * tileWidth * (int)d.c * worldMultiply - 1,
                hr * tileHeight * (int)d.r * worldMultiply - 1,
                tileWidth * (int)d.c * worldMultiply + 1,
                tileHeight * (int)d.r * worldMultiply + 1);
            e.Graphics.DrawRectangle(pen, r);
        }


        int tsaMove; byte tsaSelect, paletteIndex, currentAttr;

        byte getPaletteNo(int x2, int y2)
        {
            return getPaletteNo(x2, y2, screenNumber);
        }
        byte getPaletteNo(int x2, int y2, int screenNumber)
        {
            int x = (x2 == 0 ? 0 : x2 / (tileWidth * (int)worldEdit.tsaEdit.tsa.c * worldMultiply));
            int y = (y2 == 0 ? 0 : y2 / (tileHeight * (int)worldEdit.tsaEdit.tsa.r * worldMultiply));
            return worldEdit.paletteIndex[screenNumber, (y * worldEdit.tsaRow) + x];
        }
        byte getTsaNo(int x2, int y2)
        {
            return getTsaNo(x2, y2, screenNumber);
        }
        byte getTsaNo(int x2, int y2, int screenNumber)
        {
            int x = (x2 == 0 ? 0 : x2 / (tileWidth * (int)worldEdit.tsaEdit.tsa.c * worldMultiply));
            int y = (y2 == 0 ? 0 : y2 / (tileHeight* (int)worldEdit.tsaEdit.tsa.r * worldMultiply));
            return worldEdit.worldMap[screenNumber, x + y * worldEdit.tsaCol];
        }

        int lastX, lastY;
        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.X < 0 || e.Y < 0) return;
            if (e.X >= pictureBox1.Width || e.Y >= pictureBox1.Height) return;
            if(isShiftDown && e.Button == MouseButtons.Left)
                mouse_tile_replace(e);

            lastX = e.X;
            lastY = e.Y;
            var otsaMove = tsaMove;
            tsaMove = getTsaNo(e.X, e.Y);
            if(otsaMove!= tsaMove)
                pictureBox2.Invalidate(true);


            var x2 = lastX;
            var y2 = lastY;
            int x = (x2 == 0 ? 0 : x2 / (tileWidth * (int)worldEdit.tsaEdit.tsa.c * worldMultiply));
            int y = (y2 == 0 ? 0 : y2 / (tileHeight * (int)worldEdit.tsaEdit.tsa.r * worldMultiply));

            SetTsaText(tsaMove);
            label3.Text = worldEdit.attr[screenNumber, (y * worldEdit.tsaRow) + x].ToString();
            label7.Text = worldEdit.paletteIndex[screenNumber, (y * worldEdit.tsaRow) + x].ToString();

        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.X < 0 || e.Y < 0) return;
            int x = (e.X == 0 ? 0 : e.X / (tileWidth * (int)worldEdit.tsaEdit.tsa.c * worldMultiply));
            int y = (e.Y == 0 ? 0 : e.Y / (tileHeight * (int)worldEdit.tsaEdit.tsa.r * worldMultiply));
            if (e.Button == MouseButtons.Right)
            {
                tsaSelect = getTsaNo(e.X, e.Y);
                paletteIndex = getPaletteNo(e.X, e.Y);
                currentAttr = worldEdit.attr[screenNumber, (y * worldEdit.tsaRow) + x];
                pictureBox2.pic.Invalidate();
            }
            else if(e.Button == MouseButtons.Left)
            {
                mouse_tile_replace(e);
            }
        }
        void mouse_tile_replace(MouseEventArgs e)
        {
            int x = (e.X == 0 ? 0 : e.X / (tileWidth * (int)worldEdit.tsaEdit.tsa.c * worldMultiply));
            int y = (e.Y == 0 ? 0 : e.Y / (tileHeight * (int)worldEdit.tsaEdit.tsa.r * worldMultiply));
            if ((worldEdit.worldMap[screenNumber, x + y * worldEdit.tsaCol] != tsaSelect) ||
                (worldEdit.paletteIndex[screenNumber, (y * worldEdit.tsaRow) + x] != paletteIndex ) ||
                (worldEdit.attr[screenNumber, (y * worldEdit.tsaRow) + x] != currentAttr))
            {
                worldEdit.worldMap[screenNumber, x + y * worldEdit.tsaCol] = tsaSelect;
                worldEdit.paletteIndex[screenNumber, (y * worldEdit.tsaRow) + x] = paletteIndex;
                worldEdit.attr[screenNumber, (y * worldEdit.tsaRow) + x] = currentAttr;
                draw(screenNumber);
            }
        }

        private void pictureBox2_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.X < 0 || e.Y < 0) return;
            if (e.X >= pictureBox1.Width || e.Y >= pictureBox1.Height) return;
            int x = (e.X == 0 ? 0 : e.X / (tileWidth * (int)worldEdit.tsaEdit.tsa.c * worldMultiply));
            int y = (e.Y == 0 ? 0 : e.Y / (tileHeight * (int)worldEdit.tsaEdit.tsa.r * worldMultiply));
            tsaSelect = (byte)(x + y * worldEdit.tsaEdit.displayC);
            paletteIndex = getPaletteNo(e.X, e.Y);
            pictureBox2.pic.Invalidate();
        }

        private void WorldEdit_KeyUp(object sender, KeyEventArgs e)
        {
            isShiftDown = e.Shift;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //Form1.MMEdit.saveLevelData(worldEdit.worldMap);
        }

        private void comboBox1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                this.Focus();
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            mm.SaveLevelData(worldEdit);
            Form1.Save();
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            worldEdit = mm.getLevelData(comboBox1.SelectedIndex);
            redrawlAll();
        }
        void redrawlAll()
        {
            pictureBox2.Invalidate(true);
            draw(screenNumber);
            drawTsa();
        }

        private void pictureBox2_DoubleClick(object sender, EventArgs e)
        {
            new tsaPreset(mm.loadTsa(comboBox1.SelectedIndex)).ShowDialog();
            redrawlAll();
        }
    }
}
